package com.sihai.ehr.service.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import com.sihai.ehr.jdbc.DepartmentService;
import com.sihai.ehr.jdbc.Member;
import com.sihai.ehr.jdbc.MemberService;
import com.sihai.ehr.model.sys.User;
import com.sihai.ehr.utils.DateUtil;
import com.sihai.ehr.web.pojo.EmployeeNoPojo;
import org.apache.commons.lang.xwork.StringUtils;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.stereotype.Service;

import com.sihai.core.BaseEntity;
import com.sihai.core.DataAccessor;
import com.sihai.core.DynamicQuery;
import com.sihai.core.Limit;
import com.sihai.core.LimitedList;
import com.sihai.core.QueryCreator;
import com.sihai.core.Sorter;
import com.sihai.ehr.model.biz.EmployeeWorkExperience;
import com.sihai.ehr.model.biz.EmployeeinfoBase;
import com.sihai.ehr.model.biz.EmployeeinfoEducation;
import com.sihai.ehr.model.biz.EmployeeinfoFamily;
import com.sihai.ehr.model.biz.EmployeeinfoTrain;
import com.sihai.ehr.model.biz.EmployeeinfoWork;
import com.sihai.ehr.model.sys.Organization;
import com.sihai.ehr.service.EmployeeService;
import com.sihai.ehr.web.pojo.EmployeeinfoBasePojo;
import com.sihai.ehr.web.pojo.StaffSearchPojo;

@Service("employeeService")
public class EmployeeServiceImpl implements EmployeeService {

	@Resource
	private DataAccessor dataAccessor;

	@Override
	public void saveEmployeeBase(EmployeeinfoBase employeeinfoBase) {
		if (employeeinfoBase != null) {
            boolean isCreate = !(employeeinfoBase.getId() != null && employeeinfoBase.getId() > 0);

			dataAccessor.save(employeeinfoBase);

            //update member
            if(!isCreate){
                try {
                    saveOrUpdateMember(getEmplyeeinfoWorkByBaseId(employeeinfoBase.getId()), isCreate);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
		}
	}

	@Override
	public void saveEmployeeinfoWork(EmployeeinfoWork employeeinfoWork) {
		if (employeeinfoWork != null) {
            boolean isCreate = !(employeeinfoWork.getId() != null && employeeinfoWork.getId() > 0);
			dataAccessor.save(employeeinfoWork);

            //save member
            try {
                saveOrUpdateMember(employeeinfoWork, isCreate);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
	}

	@Override
	public List<EmployeeinfoEducation> getEducationList(
			EmployeeinfoBase employeeinfoBase, Limit limit, Sorter sorter) {
		if (employeeinfoBase == null)
			return null;
		return dataAccessor.findByHql(EmployeeinfoEducation.class,
				"from EmployeeinfoEducation where baseId=?",
				new Object[] { employeeinfoBase }, limit, sorter);
	}

	@Override
	public LimitedList<EmployeeinfoBase> searchEmployeeinfoBase(
			final EmployeeinfoBase employeeinfoBase, final int state,
			Limit limit, Sorter sorter) {
		StringBuffer hql = new StringBuffer();
		hql.append("from EmployeeinfoBase e where e.cancel='0' ");
		hql.append("and e.state='").append(state).append("' ");
		if (employeeinfoBase == null) {
			return dataAccessor.findByHql(EmployeeinfoBase.class,
					hql.toString(), null, limit, sorter);
		}

		return dataAccessor.findByQuery(EmployeeinfoBase.class,
				new QueryCreator() {

					@Override
					public Query createQuery(Session session) {
						DynamicQuery dynamicQuery = new DynamicQuery(
								"from EmployeeinfoBase e where e.cancel='0' and e.state='"
										+ state + "'");

						dynamicQuery.appendIfNotNull(" and e.name like :name",
								"name", employeeinfoBase.getName());

						return dynamicQuery.build(session);
					}
				}, limit, sorter);
	}

	public LimitedList<EmployeeinfoBasePojo> queryEmployeeinfoBasesForNOffical(
			Limit limit, Sorter sorter) {
		StringBuffer hql = new StringBuffer();
		hql.append("select new com.sihai.ehr.web.pojo.EmployeeinfoBasePojo(e.id,e.name,e.sex,e.birthday,e.compensation,e.certificate,e.school) from EmployeeinfoBase e where e.cancel='0' ");
		hql.append("and (e.state='").append('2').append("' ")
				.append("or e.state='").append('3').append("')");
		try {
			return dataAccessor.findByHql(EmployeeinfoBasePojo.class,
					hql.toString(), null, limit, sorter);
		} catch (Exception e) {
			throw new RuntimeException(
					"【读取非正式员工发生异常】【异常原因：:"
							+ e.getMessage()
							+ "】【发生地点：EmployeeServiceImpl.queryEmployeeinfoBasesForNOffical】");
		}
	}

	public EmployeeinfoWork getEmplyeeinfoWorkByBaseId(Long employeeId) {
		if (employeeId <= 0)
			return null;
		List<EmployeeinfoWork> list = dataAccessor.findByHql(
				EmployeeinfoWork.class,
				"from EmployeeinfoWork e where e.baseId.id=?",
				new Object[] { employeeId }, null, null);
		if (list != null && list.size() > 0) {
			return list.get(0);
		} else {
			return null;
		}
	}

	@Override
	public LimitedList<EmployeeinfoWork> searchEmployeeinfoWorks(
			StaffSearchPojo search, Long organizationId, final String state,
			Limit limit, Sorter sorter) {
		String hql = "from EmployeeinfoWork e where e.cancel='0' and e.baseId.state=? ";
		if (search == null) {
			return dataAccessor.findByHql(EmployeeinfoWork.class, hql,
					new Object[] { state }, limit, sorter);
		}

		Organization organization = null;
		boolean isReadTopOrg = false;
		if (search.getDepartment() != null && search.getDepartment() > 0) {
			try {
				organization = dataAccessor.get(Organization.class,
						search.getDepartment());
				if (organization.getTopOrganization() == null) {
					isReadTopOrg = true;
				}
			} catch (Exception e) {
				return null;
			}
		}
		if (search.getDepartment() == null || search.getDepartment() < 0) {
			return dataAccessor.findByHql(EmployeeinfoWork.class, hql,
					new Object[] { state }, limit, sorter);
		} else if (search.getDuty() == null || search.getDuty() < 0) {
			return dataAccessor.findByHql(EmployeeinfoWork.class, hql
					+ (isReadTopOrg ? "and (e.organization.topOrganization.id="
							+ search.getDepartment()
							+ " or e.organization.id=?)"
							: " and e.organization.id=?"), new Object[] {
					state, search.getDepartment() }, limit, sorter);
		} else {
			return dataAccessor
					.findByHql(
							EmployeeinfoWork.class,
							hql
									+ (isReadTopOrg ? "and (e.organization.topOrganization.id="
											+ search.getDepartment()
											+ " or e.organization.id=?)"
											: " and e.organization.id=?")
									+ " and e.duty.id=?", new Object[] { state,
									search.getDepartment(), search.getDuty() },
							limit, sorter);
		}

	}

	@Override
	public Long getTotalCountByOrganizationId(final Long orgId,
			boolean isReadChild) {
		if (orgId > 0) {
			try {
				if (isReadChild) {
					String treepath = dataAccessor.get(Organization.class,
							orgId).getTreePath();

					final String orgRealtion = treepath;
					return this.dataAccessor.findUnique(Long.class,
							new QueryCreator() {
								@Override
								public Query createQuery(Session session) {
									return session
											.createQuery("select count(o.id) from EmployeeinfoWork o where o.organization.treePath like '" + orgRealtion + "%'");
								}
							});
				} else {
					return this.dataAccessor.findUnique(Long.class,
							new QueryCreator() {
								@Override
								public Query createQuery(Session session) {
									return session
											.createQuery("select count(o.id) from EmployeeinfoWork o where o.organization.id="
													+ orgId);
								}
							});
				}

			} catch (Exception e) {
				throw new RuntimeException(
						"【统计部门人数异常】【异常原因：:"
								+ e.getMessage()
								+ "】【发生地点：EmployeeServiceImpl.getTotalCountByOrganizationId】");
			}

		} else {
			return 0L;
		}
	}
	
	@Override
	public Long getTotalCountBySalaryStructId(final Long structId) {
		if (structId > 0) {
			try {
				return this.dataAccessor.findUnique(Long.class,
						new QueryCreator() {
							@Override
							public Query createQuery(Session session) {
								return session
										.createQuery("select count(o.id) from EmployeeinfoWork o where o.grade.salaryStructure.id="
												+ structId);
							}
						});

			} catch (Exception e) {
				throw new RuntimeException(
						"【统计部门人数异常】【异常原因：:"
								+ e.getMessage()
								+ "】【发生地点：EmployeeServiceImpl.getTotalCountByOrganizationId】");
			}

		} else {
			return 0L;
		}
	}

	@Override
	public EmployeeinfoBase getEmployeeinfoBase(Long id) {
		if (id == null || id < 0)
			throw new RuntimeException("invalid argument exception");
		return dataAccessor.get(EmployeeinfoBase.class, id);
	}

	@Override
	public void saveEducation(EmployeeinfoEducation employeeinfoEducation) {
		if (employeeinfoEducation != null) {
			dataAccessor.save(employeeinfoEducation);
		}
	}

	@Override
	public void saveEmployeeTrain(EmployeeinfoTrain employeeinfoTrain) {
		if (employeeinfoTrain != null) {
			dataAccessor.save(employeeinfoTrain);
		}
	}

	@Override
	public void saveEmployeeExperience(
			EmployeeWorkExperience employeeWorkExperience) {
		if (employeeWorkExperience != null) {
			System.out.println("id:" + employeeWorkExperience.getId());
			dataAccessor.save(employeeWorkExperience);
		}
	}

	@Override
	public void saveEmployeeFamily(EmployeeinfoFamily employeeinfoFamily) {
		if (employeeinfoFamily != null) {
			dataAccessor.save(employeeinfoFamily);
		}
	}

	@Override
	public List<EmployeeinfoBase> findForDutyProxy(String type, String name) {
		if (StringUtils.isNotBlank(name)) {
			return dataAccessor
					.findByHql(
							EmployeeinfoBase.class,
							"select new EmployeeinfoBase(id, name) from EmployeeinfoBase where cancel <> '1' and state='1' and name like '%"
									+ name + "%'", null, null, null);
		}

		// TODO:根据type得到不同类型(权限)的雇员
		return dataAccessor
				.findByHql(
						EmployeeinfoBase.class,
						"select new EmployeeinfoBase(id, name) from EmployeeinfoBase where cancel <> '1' and state='1'",
						null, null, null);
	}

	@Override
	public String getEmployeeNo(final String emp) {
		return this.dataAccessor.findUnique(String.class, new QueryCreator() {
			@Override
			public Query createQuery(Session session) {
				return session
						.createQuery("select max(o.workNo) from EmployeeinfoWork o where o.workNo like '"
								+ emp + "%'");
			}
		});

	}

	@Override
	public void removeEmployee(final String strIds, final int state) {
		if (strIds == null || strIds.isEmpty()) {
			return;
		}

		dataAccessor.batchUpdate(new QueryCreator() {
			@Override
			public Query createQuery(Session session) {
				if (state == 1) {
					return session.createQuery(String.format("update EmployeeinfoWork b set b.cancel='1' where b.id in (%s)", strIds));
				} else
                    return session.createQuery(String.format("update EmployeeinfoBase b set b.cancel='1' where b.id in (%s)", strIds));
            }
        });

        if(state == 1){
            try {
                deleteMember(strIds);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

	@Override
	public void removeEmpRelate(Long id, int state) {
		if (state == 1) {
			dataAccessor.delete(new EmployeeinfoEducation(id));
		} else if (state == 2) {
			dataAccessor.delete(new EmployeeinfoTrain(id));
		} else if (state == 3) {
			dataAccessor.delete(new EmployeeWorkExperience(id));
		} else if (state == 4) {
			dataAccessor.delete(new EmployeeinfoFamily(id));
		}

	}

	@Override
	public void updateEmployeeRelatedEntity(BaseEntity entity) {
		dataAccessor.update(entity);
	}

	@Override
	public EmployeeinfoWork getEmployeeinfoWork(Long id) {
		if (id == null || id <= 0) {
			throw new RuntimeException(
					"invalid arguement exception,id must be greater than 0");
		}
		return dataAccessor.get(EmployeeinfoWork.class, id);
	}

	@Override
	public List<EmployeeinfoTrain> getTrainList(
			EmployeeinfoBase employeeinfoBase, Limit limit, Sorter sorter) {
		if (employeeinfoBase == null)
			return null;
		return dataAccessor.findByHql(EmployeeinfoTrain.class,
				"from EmployeeinfoTrain t where t.baseId=?",
				new Object[] { employeeinfoBase }, limit, sorter);
	}

	@Override
	public List<EmployeeWorkExperience> getWorkExperienceList(
			EmployeeinfoBase employeeinfoBase, Limit limit, Sorter sorter) {
		if (employeeinfoBase == null)
			return null;
		return dataAccessor.findByHql(EmployeeWorkExperience.class,
				"from EmployeeWorkExperience w where w.employeeinfoBase=?",
				new Object[] { employeeinfoBase }, limit, sorter);
	}

	@Override
	public List<EmployeeinfoFamily> getEmployeeFamilyList(
			EmployeeinfoBase employeeinfoBase, Limit limit, Sorter sorter) {
		if (employeeinfoBase == null)
			return null;
		return dataAccessor.findByHql(EmployeeinfoFamily.class,
				"from EmployeeinfoFamily f where f.employeeinfoBase=?",
				new Object[] { employeeinfoBase }, limit, sorter);

	}

	@Override
	public EmployeeinfoEducation getEmployeeinfoEducationById(Long id) {
		if (id != null) {
			String hql = "select new EmployeeinfoEducation(id,schoolName,specialty, degree,beginDate,endDate,diffMon) from EmployeeinfoEducation where id=?";
			List<EmployeeinfoEducation> edus = dataAccessor.findByHql(
					EmployeeinfoEducation.class, hql, new Object[] { id },
					null, null);
			if (edus != null && edus.size() > 0)
				return edus.get(0);
		}
		return null;
	}

	@Override
	public EmployeeinfoTrain getEmployeeinfoTrainById(Long id) {
		if (id != null) {
			String hql = "select new EmployeeinfoTrain(id,letter,trainAddress,trainContent,beginDate,endDate,diffMon) from EmployeeinfoTrain where id=?";
			List<EmployeeinfoTrain> trans = dataAccessor.findByHql(
					EmployeeinfoTrain.class, hql, new Object[] { id }, null,
					null);
			if (trans != null && trans.size() > 0)
				return trans.get(0);
		}
		return null;
	}

	@Override
	public EmployeeWorkExperience getEmployeeWorkExperienceById(Long id) {
		if (id != null) {
			String hql = "select new EmployeeWorkExperience(id,compname,job,monthlyPay,proveMan,contel,beginDate,endDate,resignReason,diffMon) from EmployeeWorkExperience where id=?";
			List<EmployeeWorkExperience> exps = dataAccessor.findByHql(
					EmployeeWorkExperience.class, hql, new Object[] { id },
					null, null);
			if (exps != null && exps.size() > 0)
				return exps.get(0);
		}
		return null;
	}

	@Override
	public EmployeeinfoFamily getEmployeeFamilyById(Long id) {
		if (id != null) {
			String hql = "select new EmployeeinfoFamily(familyRelation, compname, address, name, contel, exigenceConname, exigenceRelation, id) from EmployeeinfoFamily where id=?";
			List<EmployeeinfoFamily> fams = dataAccessor.findByHql(
					EmployeeinfoFamily.class, hql, new Object[] { id }, null,
					null);
			if (fams != null && fams.size() > 0)
				return fams.get(0);
		}
		return null;
	}

	@Override
	public EmployeeNoPojo getEmployeeNoInfoByOrgId(Long orgId) {
		if (orgId != null) {
			String hql = "select new com.sihai.ehr.web.pojo.EmployeeNoPojo(o.employeeNo, w.activity) from Organization o,WorkNo w where o.id=w.organization.id  and o.id=?";
			List<EmployeeNoPojo> empNo = dataAccessor.findByHql(
					EmployeeNoPojo.class, hql, new Object[] { orgId }, null,
					null);
			if (empNo != null && empNo.size() > 0)
				return empNo.get(0);
		}
		return null;
	}

    //查找考勤工号是否重复
    @Override
    public EmployeeinfoWork findBySalaryNo(String salaryNo) throws Exception {
        List<EmployeeinfoWork> employees = dataAccessor.findByHql(EmployeeinfoWork.class, "from EmployeeinfoWork w where w.baseId.salaryNo=? and w.baseId.state='1'", new Object[]{salaryNo}, null, null);
        if(employees != null && !employees.isEmpty()){
            return employees.get(0);
        }
        return null;
    }

    //同步员工数据到考勤库start==========================================
    private MemberService memberService;
    private void checkMemberService() throws Exception{
        if(memberService == null){
            memberService = new MemberService();
            memberService.connection();
        }
    }

    public void  initMemberDB()throws Exception{
        List<Member> members = findAllMembers();
        if(members != null && !members.isEmpty()){
            checkMemberService();
            memberService.init(members);
        }
    }

    private void saveOrUpdateMember(EmployeeinfoWork work, boolean isCreate)throws Exception{
        Member member = buildMember(work);
        checkMemberService();
        if(isCreate){
            memberService.insert(member);
        }else{
            memberService.update(member);
        }
    }

    private void deleteMember(Long employeeId)throws Exception{
        if(employeeId != null && employeeId > 0){
            memberService.delete((int)(long)employeeId);
        }
    }
    private void deleteMember(String employeeIds)throws Exception{
        if(StringUtils.isNotBlank(employeeIds)){
            memberService.delete(employeeIds);
        }
    }

    private List<Member>  findAllMembers(){
        List<EmployeeinfoWork> works = dataAccessor.findByHql(EmployeeinfoWork.class, "from EmployeeinfoWork w where w.baseId.state = '1' and w.baseId.cancel = '0'", null, null, null);
        if(works != null && !works.isEmpty()){
            List<Member> members = new ArrayList<Member>(works.size());
            for(EmployeeinfoWork work : works){
                members.add(buildMember(work));
            }
            return members;
        }
        return null;
    }

    private Member buildMember(EmployeeinfoWork work){
        if(work == null){
            return null;
        }
        Member member = new Member();
        EmployeeinfoBase employee = work.getBaseId();
        member.setUser_serial((int) (long) employee.getId()); //考勤数据库中的员工ID为EmployeeinfoBase的ID
        member.setUser_no(work.getWorkNo()); //员工工号
        member.setUser_lname(employee.getName());
        //member.setDep_no();
        member.setUser_dep((int)(long)work.getOrganization().getId());
        //member.setUser_workday(employee.getEntryDate()); //01/01/1900
        member.setUser_duty(work.getDuty().getDutyName());
        member.setUser_sex(StringUtils.equals("0", employee.getSex()) ? "男" : "女");
        member.setUser_nation(employee.getFolk());
        member.setUser_xueli(employee.getCertificate());
        member.setUser_native(employee.getCensus());
        //member.setUser_birthday(DateUtil.formatDate("yyyy-MM-dd"));
        member.setUser_id(employee.getIdcard());
        member.setUser_post(employee.getPostcode());
        //member.setUser_linkman();
        member.setUser_telephone(employee.getTel());
        return member;
    }
    //同步员工数据到考勤库end============================================
}
